qutebrowser ModeManager
In qutebrowser, there is a concept similar to Vim's Mode, with ModeManager responsible for mode management.
EventFilter.handle_event
Driven by keyboard input, when the EventFilter class receives a keyboard event, it will obtain the current modeman (ModeManager) for processing:
# EventFilter
def _handle_key_event(self, event: QKeyEvent) -> bool:
active_window = objects.qapp.activeWindow()
if active_window not in objreg.window_registry.values():
return False
try:
man = modeman.instance('current')
# handle key event by current ModeManger
return man.handle_event(event)
except objreg.RegistryUnavailableError:
return False
ModeManager.handle_event
The handle_event
method of ModeManager will use a table lookup method to find the corresponding handler and call it:
def handle_event(self, event: QEvent) -> bool:
# Map
handlers: Mapping[QEvent.Type, Callable[[QKeyEvent], bool]] = {
QEvent.Type.KeyPress: self._handle_keypress,
QEvent.Type.KeyRelease: self._handle_keyrelease,
QEvent.Type.ShortcutOverride:
functools.partial(self._handle_keypress, dry_run=True),
}
handler = handlers[event.type()]
# call handler
return handler(cast(QKeyEvent, event))
ModeManager listens for three types of events:
QEvent.Type.KeyPress
: Key pressQEvent.Type.KeyRelease
: Key releaseQEvent.Type.ShortcutOverride
: Shortcut
Handler Map
在 modeman.py
的 init 全局函数中,完成了向 ModeManager 中注册模式。具体代码如下:
def init(win_id: int, parent: QObject) -> 'ModeManager':
"""Initialize the mode manager and the keyparsers for the given win_id."""
commandrunner = runners.CommandRunner(win_id)
modeman = ModeManager(win_id, parent)
objreg.register(
'mode-manager',
modeman,
scope='window',
window=win_id)
hintmanager = hints.HintManager(win_id, parent=parent)
objreg.register('hintmanager', hintmanager, scope='window',
window=win_id, command_only=True)
modeman.hintmanager = hintmanager
log_sensitive_keys = 'log-sensitive-keys' in objects.debug_flags
keyparsers: ParserDictType = {
usertypes.KeyMode.normal:
modeparsers.NormalKeyParser(
win_id=win_id,
commandrunner=commandrunner,
parent=modeman),
usertypes.KeyMode.hint:
modeparsers.HintKeyParser(
win_id=win_id,
commandrunner=commandrunner,
hintmanager=hintmanager,
parent=modeman),
usertypes.KeyMode.insert:
modeparsers.CommandKeyParser(
mode=usertypes.KeyMode.insert,
win_id=win_id,
commandrunner=commandrunner,
parent=modeman,
passthrough=True,
do_log=log_sensitive_keys,
supports_count=False),
usertypes.KeyMode.passthrough:
modeparsers.CommandKeyParser(
mode=usertypes.KeyMode.passthrough,
win_id=win_id,
commandrunner=commandrunner,
parent=modeman,
passthrough=True,
do_log=log_sensitive_keys,
supports_count=False),
usertypes.KeyMode.command:
modeparsers.CommandKeyParser(
mode=usertypes.KeyMode.command,
win_id=win_id,
commandrunner=commandrunner,
parent=modeman,
passthrough=True,
do_log=log_sensitive_keys,
supports_count=False),
usertypes.KeyMode.prompt:
modeparsers.CommandKeyParser(
mode=usertypes.KeyMode.prompt,
win_id=win_id,
commandrunner=commandrunner,
parent=modeman,
passthrough=True,
do_log=log_sensitive_keys,
supports_count=False),
usertypes.KeyMode.yesno:
modeparsers.CommandKeyParser(
mode=usertypes.KeyMode.yesno,
win_id=win_id,
commandrunner=commandrunner,
parent=modeman,
supports_count=False),
usertypes.KeyMode.caret:
modeparsers.CommandKeyParser(
mode=usertypes.KeyMode.caret,
win_id=win_id,
commandrunner=commandrunner,
parent=modeman,
passthrough=True),
usertypes.KeyMode.set_mark:
modeparsers.RegisterKeyParser(
mode=usertypes.KeyMode.set_mark,
win_id=win_id,
commandrunner=commandrunner,
parent=modeman),
usertypes.KeyMode.jump_mark:
modeparsers.RegisterKeyParser(
mode=usertypes.KeyMode.jump_mark,
win_id=win_id,
commandrunner=commandrunner,
parent=modeman),
usertypes.KeyMode.record_macro:
modeparsers.RegisterKeyParser(
mode=usertypes.KeyMode.record_macro,
win_id=win_id,
commandrunner=commandrunner,
parent=modeman),
usertypes.KeyMode.run_macro:
modeparsers.RegisterKeyParser(
mode=usertypes.KeyMode.run_macro,
win_id=win_id,
commandrunner=commandrunner,
parent=modeman),
}
for mode, parser in keyparsers.items():
modeman.register(mode, parser)
return modeman
本文作者:Maeiee
版权声明:如无特别声明,本文即为原创文章,版权归 Maeiee 所有,未经允许不得转载!
喜欢我文章的朋友请随缘打赏,鼓励我创作更多更好的作品!